package codetop.microsoft.temp;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: 18362
 * @Create: 2022-09-08 15:57:31 星期四
 */

public class Main {

    public static ExecutorService threadPool = Executors.newFixedThreadPool(6);
    public static ReentrantLock lock = new ReentrantLock();
    public static ReentrantLock lock2 = new ReentrantLock();
    public static Condition notFull = lock.newCondition();
    public static Condition notEmpty = lock.newCondition();
    public static int capacity = 10;
    public static Queue<Integer> queue = new LinkedList<>();
    public static BlockingQueue<Integer> queue2 = new LinkedBlockingQueue<>(capacity);
    public static volatile int cnt = 0;
    public static volatile int k = 0;
    public static int MAX_CNT = 100;
    public static volatile int[] nums = new int[MAX_CNT];

    static class ProducerTask implements Runnable {

        private Random random = new Random();

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (cnt < MAX_CNT && queue.size() == capacity)
                        notFull.await();
                    if (cnt >= MAX_CNT) {
                        notEmpty.signalAll();
                        System.out.println("Producer exit");
                        break;
                    }
                    int x = random.nextInt(10000);
                    queue.offer(x);
                    System.out.println("Produce: " + x);
                    cnt++;
                    notEmpty.signalAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }

    static class ConsumerTask implements Runnable {

        private Random random = new Random();
        private CountDownLatch latch;

        public ConsumerTask(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    while (k < MAX_CNT && queue.isEmpty())
                        notEmpty.await();
                    if (k >= MAX_CNT) {
                        notFull.signalAll();
                        System.out.println("Consumer exit");
                        latch.countDown();
                        lock.unlock();
                        break;
                    }
                    int x = queue.poll();
                    System.out.println("Consume: " + x);
                    nums[k++] = x + random.nextInt(10000);
                    notFull.signalAll();
                    lock.unlock();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            threadPool.submit(new ConsumerTask(latch));
        }
        threadPool.submit(new ProducerTask());
        latch.await();
        Arrays.sort(nums);
        for (int num : nums) {
            System.out.print(num + " ");
        }
        System.out.println();
        System.out.println(cnt);
        threadPool.shutdownNow();
    }
}
